﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace Ruandao.MiniFace
{
    public abstract class RepeaterWidgetBase : WidgetBase
    {
        /// <summary>
        /// 指定数据源对象，当存在该设置项时，直接微件所处的环境上下文中获取需要列表显示的内容，
        /// 不再使用微件中的搜索条件来检索数据。
        /// DataSource是可以通过Python求值的表达式，如"ViewBag.ContentList，ViewBag.Catalog.ContentList"等等。
        /// 项模板占位符：{?ItemTemplate?}
        /// 子模板定义标记包括空模板、分隔模板和四个项模板，分三个级别一共18个模板标记。
        /// RootItem/Item/ChildItem, RootSource/ItemSource/ChildSource
        /// </summary>
        public string RootSource { get; set; }  // 不能为空。
        public string ItemSource { get; set; }  // 不能为空。
        public string ChildSource { get; set; } // 为空表示只使用两级。

        // 取值2或者3，根据ChildSource是否为空来推断嵌套级别是3层还是2层。
        public int MaxLevel { get; set; }

        public RepeaterWidgetBase()
        {
        }

        public override void Render( TemplateContext templateContext, System.IO.TextWriter writer)
        {
            InitProperties(templateContext);
            templateContext.PythonScope.SetVariable("WidgetArgs", GetWidgetArgs());

            List<Content> templateContents = this.WidgetTemplate.Contents;
            LoopRender(templateContents, templateContext, writer,  0);

            templateContext.PythonScope.RemoveVariable("WidgetArgs");
        }

        // 显示某个级别的重复项，同时 ** 递归调用 ** 自身显示下一个级别的重复项。
        private void LoopRender(List<Content> templateContents, TemplateContext templateContext, System.IO.TextWriter writer, int level)
        {
            dynamic dataCollection = null;
            string dataSource = ""; 
            string prefix=""; 
            switch (level )
            {
                case 0:
                    prefix = "Root";
                    dataCollection = SearchData(templateContext);
                    break;
                case 1:
                    prefix = "";
                    dataSource = "RootItem." + this.ItemSource;
                    dataCollection = PythonEngine.GetEngine().Execute(dataSource, templateContext.PythonScope);
                    if (dataCollection == null)
                        throw new Exception("无法找到设置为“" + dataSource + "”的数据源集合。");
                    break;
                case 2:
                    prefix = "Child";
                    if (string.IsNullOrWhiteSpace(this.ChildSource)) break;
                    dataSource = "Item." + this.ChildSource;
                    dataCollection = PythonEngine.GetEngine().Execute(dataSource, templateContext.PythonScope);
                    if (dataCollection == null)
                        throw new Exception("无法找到设置为“" + dataSource + "”的数据源集合。");
                    break;
            }
            if (level < this.MaxLevel )
            {
                // 以下模板无需{?...?}占位符。
                string emptyTemplate = prefix + "EmptyTemplate";

                if (dataCollection == null || dataCollection.Count == 0)
                {
                    foreach (var sub in this.WidgetTemplate.TemplateItems[emptyTemplate])
                    {
                        sub.Render(templateContext, writer);
                    }
                    return;
                }
            }
            foreach (var content in templateContents)
            {
                var template = content as TemplateItem;
                if (template == null)
                {
                    content.Render(templateContext, writer);
                    continue;
                }

                // 渲染子模板。
                if (template.ItemName != "ItemTemplate")
                {
                    throw new Exception("不支持的子模板占位符：{?" + template.ItemName + "?}。");
                }
                if ( dataCollection != null )
                {
                    ItemRender(templateContext, writer, level, prefix, dataCollection);
                }
                else throw new Exception("在childitemtemplate中不再允许出现{??}项模板。");
            }
        }

        private void ItemRender(TemplateContext templateContext, System.IO.TextWriter writer, int level, string prefix, dynamic dataCollection)
        {
            // 以下模板无需{??}占位符。
            string sepratorTemplate = prefix + "SepratorTemplate";  //

            // 下述四个模板是项模板，可以使用重复项中的属性数据。
            // 占位符都是{?ItemTemplate?}，根据{?ItemTemplate?}出现的位置可以判定级别。
            string itemTemplate = prefix + "ItemTemplate";
            string firstItemTemplate = prefix + "FirstItemTemplate"; //
            string alternateItemTemplate = prefix + "AlternateItemTemplate"; //
            string currentItemTemplate = prefix + "CurrentItemTemplate"; //

            int itemCounter = 0;
            foreach (var item in dataCollection)
            {
                itemCounter++;
                templateContext.PythonScope.SetVariable(prefix + "ItemCounter", itemCounter);
                templateContext.PythonScope.SetVariable(prefix + "Item", item);

                string templateName = itemTemplate;
                if (itemCounter % 2 == 0 && 
                    this.WidgetTemplate.TemplateItems.ContainsKey(alternateItemTemplate) )
                {
                    templateName = alternateItemTemplate;
                }
                if (itemCounter == 1 && 
                    this.WidgetTemplate.TemplateItems.ContainsKey(firstItemTemplate))
                {
                    templateName = firstItemTemplate;
                }
                // if( item.Id == ? // 当前项的设置应该使用标识，以后再考虑。。。
                List<Content> contents = this.WidgetTemplate.TemplateItems[templateName];

                if (contents == null)
                {
                    throw new Exception("微件中缺少必要的模板定义：<?" + templateName + "?>");
                }

                LoopRender(contents, templateContext, writer, level + 1);

                if (this.WidgetTemplate.TemplateItems.ContainsKey(sepratorTemplate) && 
                    itemCounter < dataCollection.Count)
                {
                    List<Content> seprator = this.WidgetTemplate.TemplateItems[sepratorTemplate];
                    foreach (var s in seprator) s.Render(templateContext, writer);
                }

                templateContext.PythonScope.RemoveVariable(prefix + "Item");
                templateContext.PythonScope.RemoveVariable(prefix + "ItemCounter");
            }
        }

        protected abstract dynamic SearchData(TemplateContext templateContext);
        protected virtual void InitProperties(TemplateContext templateContext)
        {
            if (Properties.ContainsKey("ItemSource")) this.ItemSource = Properties["ItemSource"];
            if (Properties.ContainsKey("ChildSource")) this.ChildSource = Properties["ChildSource"];
            if (string.IsNullOrWhiteSpace(this.ChildSource))
            {
                this.MaxLevel = 2;
            }
        }
        protected virtual System.Dynamic.ExpandoObject GetWidgetArgs()
        {
            dynamic widgetArgs = new System.Dynamic.ExpandoObject();
            widgetArgs.ItemSource = this.ItemSource;
            widgetArgs.ChildSource = this.ChildSource;
            return widgetArgs;
        }
    }
}
